#include <func.h>
#include <unistd.h>

typedef enum {
    OPERATION_DOWNLOAD_FILE= 1,
    OPERATION_UPLOAD_FILE= 2,
}operation_t;

int recvn(int sockfd, void * buff, int len);
int sendn(int sockfd, const void * buff, int len);

void recvFile(int sockfd);
void sendFile(int sockfd);

int main()
{
    //创建客户端的套接字
    int clientfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(clientfd, -1, "socket");

    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    //指定使用的是IPv4的地址类型 AF_INET
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8080);
    serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    //连接服务器
    int ret = connect(clientfd, (struct sockaddr*)&serveraddr, 
                      sizeof(serveraddr));
    ERROR_CHECK(ret, -1, "connect");
    printf("connect success.\n");

    printf("input a number: 1 下载文件，2 上传文件\n");
    int flag = 0;//发送接收文件的标志位
    scanf("%d", &flag);
    printf("flag:%d\n", flag);
    ret = send(clientfd, &flag, sizeof(flag), 0);
    printf(" 11 send %d bytes.\n", ret);

    if(flag == OPERATION_DOWNLOAD_FILE) {
        recvFile(clientfd);//下载文件
    } else if(flag == OPERATION_UPLOAD_FILE){
        sendFile(clientfd);//上传文件
    }

    close(clientfd);
    return 0;
}

//接收确定的字节数的数据
int recvn(int sockfd, void * buff, int len)
{
    int left = len;
    char * pbuf = buff;
    int ret = -1;
    while(left > 0) {
        ret = recv(sockfd, pbuf, left, 0);
        if(ret == 0) {
            break;
        } else if(ret < 0) {
            perror("recv");
            return -1;
        }
        left -= ret;
        pbuf += ret;
    }
    return len - left;
}

//sendn函数可以发送确定的字节数
int sendn(int sockfd, const void * buff, int len)
{
    int left = len;
    const char* pbuf = buff;
    int ret = -1;
    while(left > 0) {
        ret = send(sockfd, pbuf, left, 0);
        if(ret < 0) {
            perror("send");
            return -1;
        }
        left -= ret;
        pbuf += ret;
    }
    return len - left;
}

void recvFile(int sockfd) {
    printf("recv file begin\n");
    int length = 500000;
    //打开文件句柄
    int fd = open("bigfile.avi", O_CREAT|O_RDWR |O_TRUNC, 0644);
    char buff[1000] = {0};
    int total = 0, ret = 0;
    //接收文件内容本身
    while(total < length) {
        memset(buff, 0, sizeof(buff));
        ret = recv(sockfd, buff, sizeof(buff), 0);
        printf("ret:%d\n", ret);
        if(ret > 0) {
            total += ret;
            write(fd, buff, ret);//写入本地文件
            printf("recv %d bytes.\n", total);
        } else if(ret == 0) {
            perror("recv");
            break;
        }
        usleep(100000);
    }
    close(fd);
    printf(">> file recv over.\n");
}

void sendFile(int sockfd)
{
    printf("send file begin\n");
    int length = 500000;
    //打开文件句柄
    int fd = open("upload.avi", O_RDWR);
    char buff[1000] = {0};
    int total = 0, ret = 0;
    //接收文件内容本身
    while(total < length) {
        memset(buff, 0, sizeof(buff));
        ret = read(fd, buff, sizeof(buff));
        if(ret == 0) {
            break;
        }else if(ret > 0) {
            ret = sendn(sockfd, buff, ret);
            total += ret;
            printf(">> upload %d bytes.\n", total);
        }
        usleep(100000);
    }
    close(fd);
    printf(">> file send over.\n");
}
